Basics
$ SELECT ROW(NULL, NULL) IS NULL;
-> true
$ SELECT ROW(10, 10) IS NOT NULL;
-> true
Unusual
$ SELECT ROW(10, NULL) IS NULL;
-> false
$ SELECT ROW(10, NULL) IS NOT NULL;
-> false
$ SELECT NOT ROW(10, NULL) IS NULL;
-> true
Wait, what?
$ SELECT ROW(NULL) IS NULL;
-> true
$ SELECT ROW(ROW(NULL)) IS NULL;
-> false
What's going on there?
Values inside of a composite type are checked for NULL
value equality,
which is not the same as recursively checking with IS NULL
!
This behavior is explained in this twitter post.
We can (ab)use this to check if a value is literally NULL
or just a value that IS NULL
:
SELECT value AS value,
value IS NULL AS is_null,
ROW(value) IS NULL AS is_null_value
FROM (VALUES (NULL), (ROW(NULL))) AS x(value);
value | is_null | is_null_value
--------+---------+---------------
<null> | t | t
() | t | f
Check out this blog post for more information on NULL
behavior.